# -*- coding: utf-8 -*-
import numpy
import math
from .device import battery_device
from .device import pv_device

class micro_system(object):

    def __init__(self, req_devices, req_settings):
        # Resources in micro grid
        self.device_list = []

        # For storage device
        self.storage_charge_pmax = None

        self.storage_discharge_pmax = None

        self.storage_soc_max = None

        self.initialize(req_devices, req_settings)

    def add_new_device(self, device):
        pass

    def remove_device(self, device):
        pass

    # req is dict contains
    def initialize(self, req_devices, req_settings):
        # Qmin and Qmax are user input or from estimation?
        if "Vnorm" in req_settings:
            self.Vnorm = req_settings["Vnorm"]
        else:
            pass#

        if "X" in req_settings:
            self.jX = req_settings["X"]
        else:
            pass#


        if "R" in req_settings:
            self.pf_boundary = req_settings["R"]
        else:
            pass

        if "pfLimit" in req_settings:
            self.pf_boundary = req_settings["pfLimit"]
        else:
            pass

        self.Qmin = 0
        self.Qmax = 0
        self.device_list = []

        # req_devices is list of dict
        for item in req_devices:
            # different type of devices
            if item["devtype"] == 111: #储能
                device = battery_device.battery_device(item)
                device.S = item["max_outpower"]*1000
                device.dev_id = item["id"]
                device.Qmin = -1*item["max_outqpower"]*1000
                device.Qmax = item["max_outqpower"]*1000

                self.Qmin = self.Qmin + device.Qmin
                self.Qmax = self.Qmax + device.Qmax

                device.soc_min = 0
                device.soc_max = item["capacity"]*1000
                device.Pmax_charge = item["rated_in_p"]*1000
                device.Pmax_discharge = item["rated_out_p"]*1000

                if self.storage_soc_max is None:
                    self.storage_charge_pmax = device.Pmax_charge
                    self.storage_discharge_pmax = device.Pmax_discharge
                    self.storage_soc_max = device.soc_max
                else:
                    self.storage_charge_pmax = self.storage_charge_pmax + device.Pmax_charge
                    self.storage_discharge_pmax = self.storage_discharge_pmax+ device.Pmax_discharge
                    self.storage_soc_max = self.storage_soc_max + device.soc_max

                self.device_list.append(device)

            elif item['devtype'] == 221: #"PV"
                device = pv_device.pv_device(item)
                device.S = item["max_outpower"]*1000
                device.dev_id = item["id"]
                device.Qmin = -1*item["max_outqpower"]*1000
                device.Qmax = item["max_outqpower"]*1000 #Need to be computed based on S and P

                self.Qmin = self.Qmin + device.Qmin
                self.Qmax = self.Qmax + device.Qmax

                self.device_list.append(device)

        self.n_active_devices = len(self.device_list)

        return

    # Compute q min and max of system
    def getQBound(self):
        return self.Qmin, self.Qmax

    # Compute q adjustment min and max of system
    def getQAdjustBound(self):
        QDecreaseLimit = 0
        QIncreaseLimit = 0
        for device in self.device_list:
            QDecreaseLimit = QDecreaseLimit + device.getQDecreaseLimit()
            QIncreaseLimit = QIncreaseLimit + device.getQIncreaseLimit()

        return QDecreaseLimit, QIncreaseLimit

    def get_lower_q_boundary(self):
        self.q_list = []
        for device in self.device_list:
            self.q_list.append(device.Qmin)

        return self.q_list

    def get_upper_q_boundary(self):
        self.q_list = []
        for device in self.device_list:
            self.q_list.append(device.Qmax)

        return self.q_list

    def get_lower_q_abs(self):
        self.q_list = []
        for device in self.device_list:
            self.q_list.append(-1*device.Qmin)

        return self.q_list

    def get_upper_q_abs(self):
        self.q_list = []
        for device in self.device_list:
            self.q_list.append(-1*device.Qmax)

        return self.q_list

    def get_decrease_q_boundary(self):
        self.q_list = []
        for device in self.device_list:
            self.q_list.append(device.Qmin - device.Q)

        return self.q_list

    def get_increase_q_boundary(self):
        self.q_list = []
        for device in self.device_list:
            self.q_list.append(device.Qmax - device.Q)

        return self.q_list

    # Compute overall power factor
    def getPowerFactor(self):
        grid_S = 0
        grid_P = 0
        for device in self.device_list:
            grid_S = grid_S + device.S

            grid_P = grid_P + device.P + device.delta_P

        return grid_P/grid_S

    def calc_power_factor(self):
        grid_S = 0
        grid_P = 0
        for device in self.device_list:
            grid_S = grid_S + device.S

            #grid_P = grid_P + device.P + device.delta_P

        return 1#grid_P/grid_S

    def calc_p_adjustment(self, QAdjustList):

        tempPAdjustList = [0] * self.n_active_devices
        '''for i in range(len(self.device_list)):
            tempPAdjustList[i] = math.sqrt(math.pow(self.device_list[i].S,2)- math.pow(self.device_list[i].Q + QAdjustList[i],2)) - self.device_list[i].P

            self.device_list[i].delta_P = tempPAdjustList[i]
            '''
        return tempPAdjustList


    def update_grid_measure(self, grid_measure):
        for device in self.micro_grid.device_list:
            device.P = 0
            device.Q = 0

            for item in grid_measure["10102"]:
                if int(item['device_id']) == device.dev_id:
                   if 'in_active_power' in item.keys():
                      P = item['in_active_power']
                      Q = item['in_reactive_power']
                      device.P = P*1000
                      device.Q = Q*1000

                   #if 'in_active_power' in item.keys():


                   break
        return

    def get_battery_outpower_bound(self):
        return self.storage_discharge_pmax

    def get_battery_soc(self, grid_measure):

        battery_soc = self.micro_grid.get_battery_soc()

